<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="Wgowj" id="Wgowj"><span data-lake-id="u33482e55" id="u33482e55">典型回答</span></h1>
  <p data-lake-id="u0ee12970" id="u0ee12970"><br></p>
  <p data-lake-id="u5a7d060e" id="u5a7d060e"><span data-lake-id="ufd85001b" id="ufd85001b">在Redis中，使用zset可以实现排行榜的功能这个大家都知道。</span></p>
  <p data-lake-id="uc6b72b05" id="uc6b72b05"><span data-lake-id="u37d2ec60" id="u37d2ec60">​</span><br></p>
  <p data-lake-id="uc3413712" id="uc3413712"><span data-lake-id="u5278d584" id="u5278d584">zset可以实现，将每个用户的得分作为zset中元素的score，将用户ID作为元素的value。使用zset提供的排序功能，可以按照分数从高到低排序，</span><strong><span data-lake-id="u786b38a7" id="u786b38a7">但是如果分数相同，按照默认的排序规则会按照value值排序</span></strong><span data-lake-id="u83d89f56" id="u83d89f56">，而不是按照时间顺序排序。</span></p>
  <p data-lake-id="ub01ed87c" id="ub01ed87c"><span data-lake-id="u439e2b38" id="u439e2b38">​</span><br></p>
  <p data-lake-id="uee001d48" id="uee001d48"><span data-lake-id="ufb1f2d27" id="ufb1f2d27">为了实现分数相同按照时间顺序排序，</span><strong><span data-lake-id="u904dde25" id="u904dde25">我们可以将分数score设置为一个浮点数，其中整数部分为得分，小数部分为时间戳</span></strong><span data-lake-id="uec107271" id="uec107271">，如下所示：</span></p>
  <p data-lake-id="ue80af19c" id="ue80af19c"><span data-lake-id="u9792eba8" id="u9792eba8">​</span><br></p>
  <blockquote data-lake-id="u96d931d5" id="u96d931d5">
   <p data-lake-id="u59871b17" id="u59871b17"><span data-lake-id="u8b804857" id="u8b804857">score = 分数 + 时间戳/1e13</span></p>
  </blockquote>
  <p data-lake-id="u281d7afd" id="u281d7afd"><span data-lake-id="u200e94d1" id="u200e94d1">​</span><br></p>
  <p data-lake-id="ub6377ddf" id="ub6377ddf"><span data-lake-id="u25247a18" id="u25247a18">假设现在的时间戳是1680417299000，除以1e13得到0.1680417299000，再加上一个固定的分数（比如10），那么最终的分数就是10.1680417299000，可以将它作为zset中某个成员的分数，用来排序。</span></p>
  <p data-lake-id="uf9fc0a38" id="uf9fc0a38"><span data-lake-id="udb28d1b6" id="udb28d1b6">​</span><br></p>
  <p data-lake-id="ub5651065" id="ub5651065"><span data-lake-id="u25027d1e" id="u25027d1e">这么做了之后，假如有四个数字：</span></p>
  <p data-lake-id="ue98e8fbe" id="ue98e8fbe"><span data-lake-id="uaf325d7b" id="uaf325d7b">​</span><br></p>
  <p data-lake-id="u1dc06e1c" id="u1dc06e1c"><span data-lake-id="u00a40757" id="u00a40757">10.1680417299000、10.1680417299011、11.1680417299000、11.1680417299011</span></p>
  <p data-lake-id="ueb7fd9ff" id="ueb7fd9ff"><span data-lake-id="u64190376" id="u64190376">​</span><br></p>
  <p data-lake-id="uafc0a352" id="uafc0a352"><span data-lake-id="ua2c06391" id="ua2c06391">他们按照倒序拍完顺序之后，会是：</span></p>
  <p data-lake-id="u78ea3291" id="u78ea3291"><span data-lake-id="u94fb37f8" id="u94fb37f8">​</span><br></p>
  <p data-lake-id="u124f92e1" id="u124f92e1"><span data-lake-id="u63b29f6a" id="u63b29f6a">11.1680417299011&gt;11.1680417299000&gt;10.1680417299011&gt;10.1680417299000</span></p>
  <p data-lake-id="u7a6b098d" id="u7a6b098d"><span data-lake-id="u3b37a52d" id="u3b37a52d">​</span><br></p>
  <p data-lake-id="uc402250c" id="uc402250c"><span data-lake-id="uc883a202" id="uc883a202">实现了分数倒序排列，分数相同时间戳大的排在了前面，这和我们的需求相反了，所以，就需要在做一次转换。</span></p>
  <p data-lake-id="u9335729c" id="u9335729c"><span data-lake-id="u0f9f0ea2" id="u0f9f0ea2">​</span><br></p>
  <blockquote data-lake-id="uf2fb3235" id="uf2fb3235">
   <p data-lake-id="u7e5de89c" id="u7e5de89c"><span data-lake-id="uddab9abd" id="uddab9abd">score = 分数 + 1-时间戳/1e13</span></p>
  </blockquote>
  <p data-lake-id="u95fe3c34" id="u95fe3c34"><span data-lake-id="u014a2746" id="u014a2746">​</span><br></p>
  <p data-lake-id="ua3d46e0a" id="ua3d46e0a"><span data-lake-id="ucecb814f" id="ucecb814f">​</span><br></p>
  <p data-lake-id="u470bf9da" id="u470bf9da"><span data-lake-id="ubb5c2b48" id="ubb5c2b48">这样可以保证分数相同时，按照时间戳从小到大排序，即先得分的先被排在前面。</span></p>
  <p data-lake-id="u75be097f" id="u75be097f"><span data-lake-id="u2bee4c4c" id="u2bee4c4c">​</span><br></p>
  <p data-lake-id="uac2a3b32" id="uac2a3b32"><span data-lake-id="u3cc82b53" id="u3cc82b53">代码实现如下：</span></p>
  <p data-lake-id="uda612643" id="uda612643"><span data-lake-id="u3175bd65" id="u3175bd65">​</span><br></p>
  <pre lang="java"><code>
import redis.clients.jedis.Jedis;
/**
*@author Hollis
**/
public class RedisZsetDemo {
    private static final String ZSET_KEY = "my_zset";

    public static void addMember(String member,Int score, long timestamp, Jedis jedis) {
        double final_score = score + 1 - timestamp / 1e13;
        jedis.zadd(ZSET_KEY, final_score, member);
    }
}

</code></pre>
 </body>
</html>